home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / assembler / progasm1.lha / SORGENTI3 / LEZIONE7w2.s < prev    next >
Text File  |  1994-11-28  |  9KB  |  339 lines

  1.  
  2. ; Lezione7w2.s    COLLISIONE TRA SPRITE DISPARI
  3. ; In questo esempio vediamo come rilevare le collisioni degli sprite dispari.
  4. ; Questa volta ci sono 2 missili a caccia dell'aereo, e uno dei 2 e` uno
  5. ; sprite dispari.
  6. ; Se lanciate il programma vedrete pero` che il missile piu` a destra non
  7. ; funziona.
  8. ; Volete ripararlo ? Leggete il commento finale!
  9.  
  10.  
  11.     SECTION    CiriCop,CODE
  12.  
  13. Inizio:
  14.     move.l    4.w,a6        ; Execbase
  15.     jsr    -$78(a6)    ; Disable
  16.     lea    GfxName(PC),a1    ; Nome lib
  17.     jsr    -$198(a6)    ; OpenLibrary
  18.     move.l    d0,GfxBase
  19.     move.l    d0,a6
  20.     move.l    $26(a6),OldCop    ; salviamo la vecchia COP
  21.  
  22. ;    Puntiamo la PIC con il solito metodo
  23.  
  24.     MOVE.L    #PIC,d0
  25.     LEA    BPLPOINTERS,A1
  26.     MOVEQ    #2-1,D1
  27. POINTBP:
  28.     move.w    d0,6(a1)
  29.     swap    d0
  30.     move.w    d0,2(a1)
  31.     swap    d0
  32.     ADD.L    #40*256,d0
  33.     addq.w    #8,a1
  34.     dbra    d1,POINTBP
  35.  
  36. ;    Puntiamo lo sprite
  37.  
  38.     LEA    SpritePointers,a1    ; Puntatori in copperlist
  39.     MOVE.L    #MIOSPRITE0,d0        ; indirizzo dello sprite in d0
  40.     move.w    d0,6(a1)
  41.     swap    d0
  42.     move.w    d0,2(a1)
  43.  
  44.     add.l    #16,a1            ; puntatore sprite 2
  45.     MOVE.L    #MIOSPRITE2,d0        ; indirizzo dello sprite in d0
  46.     move.w    d0,6(a1)
  47.     swap    d0
  48.     move.w    d0,2(a1)
  49.  
  50.     add.l    #8,a1            ; puntatore sprite 3
  51.     MOVE.L    #MIOSPRITE3,d0        ; indirizzo dello sprite in d0
  52.     move.w    d0,6(a1)
  53.     swap    d0
  54.     move.w    d0,2(a1)
  55.  
  56.     move.l    #COPPERLIST,$dff080    ; nostra COP
  57.     move.w    d0,$dff088        ; START COP
  58.     move.w    #0,$dff1fc        ; NO AGA!
  59.     move.w    #$c00,$dff106        ; NO AGA!
  60.  
  61. mouse:
  62.     cmpi.b    #$ff,$dff006    ; Linea 255?
  63.     bne.s    mouse
  64.  
  65.     bsr.s    MuoviSprite0    ; Muovi l'aereo
  66.     bsr.s    MuoviSprite2    ; Muovi il missile 1 contro l'aereo
  67.     bsr.s    MuoviSprite3    ; Muovi il missile 2 contro l'aereo
  68.     bsr.w    CheckColl    ; Controlla collisione e provvede
  69.  
  70. Aspetta:
  71.     cmpi.b    #$ff,$dff006    ; linea 255?
  72.     beq.s    Aspetta
  73.  
  74.     btst    #6,$bfe001    ; mouse premuto?
  75.     bne.s    mouse
  76.  
  77.     move.l    OldCop(PC),$dff080    ; Puntiamo la cop di sistema
  78.     move.w    d0,$dff088        ; facciamo partire la vecchia cop
  79.  
  80.     move.l    4.w,a6
  81.     jsr    -$7e(a6)    ; Enable
  82.     move.l    gfxbase(PC),a1
  83.     jsr    -$19e(a6)    ; Closelibrary
  84.     rts
  85.  
  86. ;    Dati
  87.  
  88. GfxName:
  89.     dc.b    "graphics.library",0,0
  90.  
  91. GfxBase:
  92.     dc.l    0
  93.  
  94. OldCop:
  95.     dc.l    0
  96.  
  97. ; Questa routine muove lo sprite dell'aereo in linea retta di 2 pixel per volta
  98.  
  99. MuoviSprite0:
  100.     subq.b    #1,HSTART0
  101.     rts
  102.  
  103.  
  104. ; Questa routine muove il missile. Lo fa solo se l'aereo e` abbastanza vicino
  105. ; da colpirlo.
  106.  
  107. MuoviSprite2:
  108.     cmp.b    #$b0,HSTART0
  109.     bhi.s    non_a_tiro2    ; non partire se l'aereo e` troppo a destra
  110.     subq.b    #1,VSTART2
  111.     subq.b    #1,VSTOP2
  112. non_a_tiro2:
  113.     rts
  114.  
  115.  
  116. ; Questa routine muove il missile. Lo fa solo se l'aereo e` abbastanza vicino
  117. ; da colpirlo.
  118.  
  119. MuoviSprite3:
  120.     cmp.b    #$d0,HSTART0
  121.     bhi.s    non_a_tiro3    ; non partire se l'aereo e` troppo a destra
  122.     subq.b    #1,VSTART3
  123.     subq.b    #1,VSTOP3
  124. non_a_tiro3:
  125.     rts
  126.  
  127. ; Questa routine controlla se c'e` collisione. In caso affermativo, cancella
  128. ; i due sprites che hanno scontrato, azzerando i relativi puntatori nella
  129. ; copperlist. Per distinguere quale dei 2 missili ha colpito l'aereo,
  130. ; vengono controllate le posizioni. Infatti in questo esempio i missili
  131. ; possono colpire l'aereo solo dal basso; quindi se un missile si trova
  132. ; piu` in alto dell'aereo NON PUO` averlo colpito. In questo modo riusciamo
  133. ; a capire quale dei 2 missili ha colpito l'aereo.
  134.  
  135. CheckColl:
  136.     move.w    $dff00e,d0    ; legge CLXDAT ($dff00e)
  137.                 ; una lettura di questo registro ne provoca
  138.                 ; anche la cancellazione, per cui conviene
  139.                 ; copiarselo in d0 e fare i test su d0
  140.     btst.l    #9,d0
  141.     beq.s    no_coll        ; se non c'e` collisione salta
  142.  
  143.     MOVEQ    #0,d0          ; altrimenti cancella l'aereo
  144.     LEA    SpritePointers,a1 ; puntatore sprite 0
  145.     move.w    d0,6(a1)      ; azzera puntatore sprite 0 in copperlist
  146.     move.w    d0,2(a1)
  147.  
  148. ; ora dobbiamo capire quale dei 2 missili ha colpito l'aereo.
  149. ; controlliamo l'altezza del missile piu` a destra: se si trova piu`
  150. ; in alto NON ha colpito l'aereo, altrimenti e` stato lui
  151.  
  152.     move.b    VSTART0,d1    ; legge l'altezza dell'aereo
  153.     cmp.b    VSTART3,d1    ; confronta con l'altezza del missile a destra
  154.     bhi.s    spr2_coll    ; se l'aereo e` piu` in basso
  155.                 ; (quindi VSTART0 e` MAGGIORE di VSTART3)
  156.                 ; la collisione e` causata dallo sprite 2
  157.  
  158.     LEA    SpritePointer3,a1 ; altrimenti cancella sprite 3
  159.     move.w    d0,6(a1)      ; azzera puntatore sprite 3 in copperlist
  160.     move.w    d0,2(a1)
  161.     bra.s    no_coll
  162.     
  163. spr2_coll:
  164.     LEA    SpritePointer2,a1 ; cancella sprite 2
  165.     move.w    d0,6(a1)      ; azzera puntatore sprite 2 in copperlist
  166.     move.w    d0,2(a1)
  167. no_coll:
  168.     rts
  169.  
  170.  
  171.  
  172.     SECTION    GRAPHIC,DATA_C
  173.  
  174. COPPERLIST:
  175. SpritePointers:
  176.     dc.w    $120,0,$122,0,$124,0,$126,0
  177. SpritePointer2:
  178.     dc.w    $128,0,$12a,0
  179. SpritePointer3:
  180.     dc.w    $12c,0,$12e,0,$130,0,$132,0
  181.     dc.w    $134,0,$136,0,$138,0,$13a,0,$13c,0
  182.     dc.w    $13e,0
  183.  
  184.            ; 5432109876543210
  185.     dc.w    $98,%0000000000000000    ; CLXCON  $dff098
  186.  
  187.     dc.w    $8E,$2c81    ; DiwStrt
  188.     dc.w    $90,$2cc1    ; DiwStop
  189.     dc.w    $92,$38        ; DdfStart
  190.     dc.w    $94,$d0        ; DdfStop
  191.     dc.w    $102,0        ; BplCon1
  192.     dc.w    $104,$0024    ; BplCon2
  193.     dc.w    $108,0        ; Bpl1Mod
  194.     dc.w    $10a,0        ; Bpl2Mod
  195.  
  196.             ; 5432109876543210
  197.     dc.w    $100,%0010001000000000    ; 2 bitplane lowres
  198.  
  199. BPLPOINTERS:
  200.     dc.w $e0,0,$e2,0    ;primo     bitplane
  201.     dc.w $e4,0,$e6,0    ;primo     bitplane
  202.  
  203.     dc.w    $180,$000    ; color0    ; sfondo nero
  204.     dc.w    $182,$005    ; color1    ; colore 1 del bitplane
  205.     dc.w    $184,$a40    ; color1    ; colore 2 del bitplane
  206.     dc.w    $186,$f80    ; color1    ; colore 3 del bitplane
  207.  
  208.     dc.w    $1A2,$06f    ; color17, ossia COLOR1 dello sprite0
  209.     dc.w    $1A4,$0c0    ; color18, ossia COLOR2 dello sprite0
  210.     dc.w    $1A6,$0c0    ; color19, ossia COLOR3 dello sprite0
  211.  
  212.     dc.w    $1AA,$444    ; color21, ossia COLOR1 dello sprite2
  213.     dc.w    $1AC,$888    ; color22, ossia COLOR2 dello sprite2
  214.     dc.w    $1AE,$0c0    ; color23, ossia COLOR3 dello sprite2
  215.  
  216.     dc.w    $FFFF,$FFFE    ; Fine della copperlist
  217.  
  218.  
  219. ; ************ Ecco lo sprite: OVVIAMENTE deve essere in CHIP RAM! ************
  220.  
  221. MIOSPRITE0:        ; lunghezza 6 linee
  222. VSTART0:
  223.     dc.b 180    ; Posizione verticale di inizio sprite (da $2c a $f2)
  224. HSTART0:
  225.     dc.b $d8    ; Posizione orizzontale di inizio sprite (da $40 a $d8)
  226. VSTOP0:
  227.     dc.b 186    ; 180+6=186
  228. VHBITS:
  229.     dc.b $00
  230.     dc.w    $0008,$0000
  231.     dc.w    $1818,$0000
  232.     dc.w    $2C28,$1010
  233.     dc.w    $7FF8,$0000
  234.     dc.w    $3FC0,$0000
  235.     dc.w    $01F0,$0000
  236.     dc.w    $0000,$0000
  237.  
  238. MIOSPRITE2:        ; lunghezza 16 linee
  239. VSTART2:
  240.     dc.b 224    ; Posizione verticale di inizio sprite (da $2c a $f2)
  241. HSTART2:
  242.     dc.b $86    ; Posizione orizzontale di inizio sprite (da $40 a $d8)
  243. VSTOP2:
  244.     dc.b 240
  245.     dc.b 0
  246.     dc.w    $0200,$0000
  247.     dc.w    $0200,$0000
  248.     dc.w    $0200,$0000
  249.     dc.w    $0000,$0200
  250.     dc.w    $0000,$0700
  251.     dc.w    $0000,$0700
  252.     dc.w    $0500,$0200
  253.     dc.w    $0200,$0500
  254.     dc.w    $0500,$0200
  255.     dc.w    $0200,$0500
  256.     dc.w    $1540,$0200
  257.     dc.w    $0200,$1DC0
  258.     dc.w    $0000,$1FC0
  259.     dc.w    $0000,$1740
  260.     dc.w    $0500,$0200
  261.     dc.w    $0000,$0000
  262.     dc.w    $0000,$0000
  263.  
  264. MIOSPRITE3:        ; lunghezza 16 linee
  265. VSTART3:
  266.     dc.b 224    ; Posizione verticale di inizio sprite (da $2c a $f2)
  267. HSTART3:
  268.     dc.b $a6    ; Posizione orizzontale di inizio sprite (da $40 a $d8)
  269. VSTOP3:
  270.     dc.b 240
  271.     dc.b 0
  272.     dc.w    $0200,$0000
  273.     dc.w    $0200,$0000
  274.     dc.w    $0200,$0000
  275.     dc.w    $0000,$0200
  276.     dc.w    $0000,$0700
  277.     dc.w    $0000,$0700
  278.     dc.w    $0500,$0200
  279.     dc.w    $0200,$0500
  280.     dc.w    $0500,$0200
  281.     dc.w    $0200,$0500
  282.     dc.w    $1540,$0200
  283.     dc.w    $0200,$1DC0
  284.     dc.w    $0000,$1FC0
  285.     dc.w    $0000,$1740
  286.     dc.w    $0500,$0200
  287.     dc.w    $0000,$0000
  288.     dc.w    $0000,$0000
  289.  
  290. ;    figura della rampa di lancio
  291.  
  292. PIC:
  293.     incbin    "paesaggio.raw"
  294.  
  295.     end
  296.  
  297. Come abbiamo visto nella lezione, il registro CLXDAT ci permette di rilevare
  298. collisioni tra gruppi di sprite e non tra i singoli sprite. In questo esempio
  299. vediamo come risolvere il problema. Vi ricordo che mentre le collisioni degli
  300. sprite pari (cioe` sprite 0,2,4,6) sono sempre abiitate, quelle degli sprite
  301. dispari (1,3,5,7) devono essere abilitate mediante dei bit di controllo del
  302. registro CLXCON ( $dff098 ). Ogni sprite dispari ha un proprio bit di controllo
  303. e pertanto puo` essere abilitato indipendentemente dagli altri. Se provate ad
  304. eseguire il nostro esempio, noterete che il missile piu` a destra non funziona.
  305. Cio` avviene proprio perche` il missile piu` a destra e` uno sprite dispari
  306. (sprite 3) ed e` disabilitato. Infatti nella copperlist potete trovare
  307. l'istruzione:
  308.            ; 5432109876543210
  309.     dc.w    $98,%0000000000000000
  310.  
  311. Che disabilita per le collisioni tutti gli sprite dispari (per il significato
  312. preciso di tutti i bit guardate nella lezione). Per abilitare lo sprite 3,
  313. si deve settare a 1 il bit 13, cioe` modificare l'istruzione copper come segue:
  314.  
  315.            ; 5432109876543210
  316.     dc.w    $98,%0010000000000000
  317.  
  318. Provate ad eseguire l'esempio, e vedrete che ora il missile funziona!
  319.  
  320. Un altro problema delle collisioni e` che il registro CLXDAT rivela collisioni
  321. tra gruppi di sprite, e non tra i singoli sprite. Nel nostro esempio ci sono
  322. i 2 missili che appartengono allo stesso gruppo. Quindi quando c'e` una 
  323. collisione non possiamo sapere quale dei 2 missili ha colpito l'aereo leggendo
  324. il registro CLXDAT. Per farlo il metodo piu` usato e` quello di controllare le
  325. posizioni degli sprite. In questo esempio particolarmente semplice, basta
  326. controllare se lo sprite piu` a destra sia o meno al di sopra dell'aereo,
  327. come abbiamo spiegato piu` in dettaglio nel commento alla routine CheckColl.
  328. In situazioni piu` complesse con gli sprite che si muovono in piu` direzioni
  329. e` necessario fare dei controlli piu` accurati, basandosi sia sulle posizioni
  330. verticali che su quelle orizzontali. Il principio e` comunque sempre lo stesso.
  331.  
  332. Potete verificare che la nostra routine individua sempre il missile giusto
  333. modificando la posizione di partenza dello sprite piu` a destra.
  334. Il valore iniziale di HSTART3 e` $a6 e garantisce al misssile di colpire
  335. l'aereo. Sostituite $a6 con $b6. Se eseguite l'esempio vedrete che il missile
  336. si trova troppo a destra e pertanto manchera` l'aereo. Ma non temete! 
  337. Il secondo fara` comunque centro!
  338.  
  339.